package com.shiro;

import com.service.CacheService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

/**
 * 功能:
 * Version: 1.0
 * Author: DR.YangLong
 * Date: 2014/7/20
 * Time: 12:14
 * Email:410357434@163.com
 * Editor:
 */
public class UserRealm extends AuthorizingRealm {
    @Resource(name = "cacheService")
    private CacheService cacheService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        User user=(User)principalCollection.fromRealm(getName()).iterator().next();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        /*//从数据获取角色和权限赋予验证通过的用户
        authorizationInfo.setRoles(userService.findRoles(username));
        authorizationInfo.setStringPermissions(userService.findPermissions(username));*/
        Set<String> roles=new HashSet<String>();
        roles.add("teacher");
        authorizationInfo.setRoles(roles);
        return authorizationInfo;
    }

    /**
     * 第一步，doGetAuthenticationInfo获取用户存在系统数据库的信息，第二步，MyCredentialsMatcher匹配验证，第三步，doGetAuthorizationInfo进行授权
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String)authenticationToken.getPrincipal();
        /*//数据库中获取用户
        User user = userService.findByUsername(username);*/
        User user=cacheService.getUser(1);

        if(user == null) {
            throw new UnknownAccountException();//没找到帐号
        }

        if(Boolean.TRUE.equals(user.isLocked())) {
            throw new LockedAccountException(); //帐号锁定
        }

        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，
        // 如果觉得人家的不好可以自定义实现
        //这里的第一个构造参数将作为principalCollection一直传递
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user, //用ID
                user.getPassword(), //密码
                null,
                getName()  //realm name
        );
        return authenticationInfo;
    }


    /**
     * 获取认证信息在缓存中的键值
     * 此方法可以自定义认证信息在缓存中的键值，可以使用唯一标识和信息对应的方式
     * 此处的principals为此类中doGetAuthenticationInfo方法设置的principal，
     * 如果此realm前面还有realm，将有多个principal
     *
     * @param principals 凭证
     * @return key
     */
    @Override
    protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
        User user=(User)principals.fromRealm(getName()).iterator().next();
        String key="Authr_"+user.getId();
        return key;
    }

    /**
     * 此方法登录时不会调用，且使用缓存时才调用此方法，默认使用传入的token键值作为缓存key，
     * 此方法在登出时调用，返回值必须和
     * {@link #getAuthenticationCacheKey(org.apache.shiro.authc.AuthenticationToken)}相同
     * <p/>
     * {@link org.apache.shiro.realm.AuthenticatingRealm#getAuthenticationCacheKey(org.apache.shiro.subject.PrincipalCollection)}
     *
     * @param principals
     * @return
     */
    @Override
    protected Object getAuthenticationCacheKey(PrincipalCollection principals) {
        return super.getAuthenticationCacheKey(principals);
    }

    /**
     * 认证缓存key，登录时调用，默认使用token值，使用缓存时才调用此方法
     * {@link org.apache.shiro.realm.AuthenticatingRealm#getAuthenticationCacheKey(org.apache.shiro.authc.AuthenticationToken)}
     *
     * @param token token
     * @return key
     */
    protected Object getAuthenticationCacheKey(AuthenticationToken token) {
        return super.getAuthenticationCacheKey(token);
    }

}
